﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Web;
using System.Xml;
using System.ComponentModel;

using System.Net.NetworkInformation;
using VNet.VisiSuite.Common.Logger;
using VNet.VisiSuite.Common.Helper;
using VNet.VisiSuite.Common;

namespace VNet.VisiSuite.VisiBoard.BusinessLogic
{

    // Callback for each time new data is available from the VisiBox.
    public delegate bool onDataAvailable();

    public class VisiBox
    {

        public enum VisiBoxError
        {
            None,
            MismatchedBraider,
            Offline
        };

        // Registry keys for configuring connection to VisiBox
        private string _hardware_url;
        private int _hardware_poll_timeout = 5000;
        private int _hardware_poll_interval = 30000;

        private int _clear_key = 0;

        private string _cell_name = "";
        private string _braider_type = "";

        // Queue of events from VisiBox hardware
        private ConcurrentQueue<VisiBoxEvent> _events;
        private VisiBoxError _error = VisiBoxError.None;
        private bool _error_changed = false;
        private readonly object _error_lock = new Object();
        private bool _transitioned_to_online = false;

        private readonly object _machine_running_lock = new Object();
        private bool _machine_running = false;  // Is the machine running.
        private DateTime _machine_running_since = DateTime.Now;  // The time when the machine started "running".

        // Thread to run polling loop on.
        BackgroundWorker _worker = null;
        bool _stopped;  // was the thread stopped

        private string _hardware_ip_address = "";

        // Message related data
        private readonly int _msg_timeout = 180 * 1000;  // 3 minutes
        private readonly AutoResetEvent _msg_timeout_event = null;
        private ConcurrentQueue<string> _msg_queue = null;

        // Callback when events are available from the VisiBox hardware.
        private onDataAvailable _todo_when_data_available = null;

        private string _app_version = "N/A";

        static private VisiBox _instance = null;

        public VisiBox()
        {

            // Initialize values from registry.
            var reg = RegistryHelper.OpenRegistryVisi(CommonConstants.RegistryVisiSuite, false);

            if (reg.GetValue("HardwarePollTimeout") != null)
                _hardware_poll_timeout = (int)reg.GetValue("HardwarePollTimeout");
            if (_hardware_poll_timeout <= 0)
                _hardware_poll_timeout = 5000;

            if (reg.GetValue("HardwarePollInterval") != null)
                _hardware_poll_interval = 1000 * (int)reg.GetValue("HardwarePollInterval");
            if (_hardware_poll_interval <= 3000)
                _hardware_poll_interval = 3000;

            _hardware_url = (string)reg.GetValue("HardwareURL");

            _events = new ConcurrentQueue<VisiBoxEvent>();

            _hardware_ip_address = ""; // "192.168.1.141";
            _msg_timeout_event = new AutoResetEvent(false);
            _msg_queue = new ConcurrentQueue<string>();

        }

        ~VisiBox()
        {
            stop();
        }

        static public VisiBox instance()
        {
            return (_instance != null ? _instance : _instance = new VisiBox());
        }

        public VisiBoxError error()
        {
            VisiBoxError err = VisiBoxError.None;
            lock (_error_lock)
            {
                err = _error;
            }
            return err;
        }

        private void error(VisiBoxError err)
        {
            lock (_error_lock)
            {
                if (_error != err)
                {
                    _transitioned_to_online = false;
                    if (err == VisiBoxError.Offline)
                    {
                        // Transition to offline
                        machineRunning(false, DateTime.Now);
                        VisiBoxEvent evt = new VisiBoxEvent(0, DateTime.Now, true);
                        evt.appendReason(VisiBoxEvent.OFFLINE);
                        _events.Enqueue(evt);
                        enqueueMessageFromVisiBox(null); // force processing of data now.
                    }
                    else if (err == VisiBoxError.None)
                    {
                        // Transition to online.
                        VisiBoxEvent evt = new VisiBoxEvent(0, DateTime.Now, false);
                        evt.appendReason(VisiBoxEvent.OFFLINE);
                        _events.Enqueue(evt);
                        _transitioned_to_online = true;
                        enqueueMessageFromVisiBox(null); // force processing of data now.
                    }

                    _error = err;
                    _error_changed = true;
                }
            }
        }

        private bool transitionedToOnline()
        {
            bool val = false;
            lock (_error_lock)
            {
                val = _transitioned_to_online;
            }
            return val;
        }

        private void transitionedToOnline(bool val)
        {
            lock (_error_lock)
            {
                _transitioned_to_online = val;
            }
        }

        // Return true if the error has changed since the last time we called this function.
        private bool errorChanged()
        {
            bool change = false;
            lock (_error_lock)
            {
                change = _error_changed;
                _error_changed = false;
            }
            if (change == true)
            {
                bool xx = false;
            }
            return change;
        }

        public bool IsStarted
        {
            get
            {
                bool started = false;

                if (_worker != null && _worker.IsBusy)
                    started = true;

                return started;
            }
        }


        public bool machineRunning()
        {

            bool ret = false;
            lock (_machine_running_lock)
            {
                TimeSpan diff = DateTime.Now.Subtract(_machine_running_since);
                ret = _machine_running && diff.TotalSeconds >= 10.0;
            }
            return ret;
 
        }

        private void machineRunning(bool state, DateTime when)
        {
            lock (_machine_running_lock)
            {
                if (state != _machine_running)
                {
                    _machine_running_since = when;
                    _machine_running = state;
                }
            }
        }

        private bool getVisiBoxIpAddress()
        {
            bool success = false;
            _hardware_ip_address = "";

            try
            {
                string visibox_hostname = string.Format("VBOX{0}.local", _cell_name);
                System.Net.IPHostEntry host = System.Net.Dns.GetHostEntry(visibox_hostname);
                for (int ii = 0; ii < host.AddressList.Length; ++ii)
                {
                    if (host.AddressList[ii].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)  // ipv4 only
                    {
                        _hardware_ip_address = host.AddressList[ii].ToString();
                        success = true;
                        break;
                    }
                }
                if (string.IsNullOrWhiteSpace(_hardware_ip_address))
                {
                    success = false;
                }
            }
            catch (Exception ex)
            {
                FileLog.Error("getVisiBoxIpAddress() - ", ex);
            }

            if (!success)
            {
                try
                {
                    string visibox_hostname = string.Format("VBOX{0}", _cell_name);
                    System.Net.IPHostEntry host = System.Net.Dns.GetHostEntry(visibox_hostname);
                    for (int ii = 0; ii < host.AddressList.Length; ++ii)
                    {
                        if (host.AddressList[ii].AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)  // ipv4 only
                        {
                            _hardware_ip_address = host.AddressList[ii].ToString();
                            success = true;
                            break;
                        }
                    }
                    if (string.IsNullOrWhiteSpace(_hardware_ip_address))
                    {
                        success = false;
                    }
                }
                catch (Exception ex)
                {
                    FileLog.Error("getVisiBoxIpAddress() - ", ex);
                }
            }

            return success;
        }

        private string getUrl()
        {
            string url = _hardware_url;
            if (string.IsNullOrEmpty(url))
            {
                if (string.IsNullOrEmpty(_hardware_ip_address))
                    getVisiBoxIpAddress();

                url = string.Format("http://{0}:8080/api/rawdata/", _hardware_ip_address);
            }

            url += "?action=get&cell=" + _cell_name;

            return url;
        }

        private string clearUrl(int key, string when)
        {
            string url = _hardware_url;
            if (string.IsNullOrEmpty(url))
            {
                if (string.IsNullOrEmpty(_hardware_ip_address))
                    getVisiBoxIpAddress();

                url = string.Format("http://{0}:8080/api/rawdata/", _hardware_ip_address);
            }

            url += "?action=clear&key=" + key.ToString() + "&when=" + when + "&cell=" + _cell_name;

            return url;
        }


        public bool start(string cell_name, string braider_type, onDataAvailable when_data_available, string app_version)
        {
            bool success = false;

            try
            {
                _app_version = app_version;

                if (cell_name != null && cell_name.Length > 0 && _worker == null && when_data_available != null)
                {
                    _cell_name = cell_name;
                    _braider_type = braider_type;
                    _stopped = false;
                    _todo_when_data_available = when_data_available;

                    // if (string.IsNullOrEmpty(_hardware_url))
                    // {
                    //    _hardware_url = string.Format("http://vbox{0}.local:8080/api/rawdata/", cell_name);
                    // }

                    _worker = new BackgroundWorker();
                    _worker.WorkerReportsProgress = true;
                    _worker.WorkerSupportsCancellation = true;
                    _worker.DoWork += new DoWorkEventHandler(doWork);
                    _worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(workComplete);
                    _worker.ProgressChanged += new ProgressChangedEventHandler(reportProgress);
                    _worker.RunWorkerAsync(null);

                    success = true;
                }

            }
            catch (Exception ex)
            {
                FileLog.Error("Error starting VisiBox: ", ex);
                success = false;
            }

            return success;
        }

        public bool stop()
        {
            if (_worker != null)
            {
                _stopped = true;
                _worker.CancelAsync();
            }
            return true;
        }

#if OLD_WAY
        // Clear all data where key is <= this value
        public void clearEvents(int key)
        {
            _clear_key = key;

            HttpWebRequest request;
            HttpWebResponse response;

            string clear_url = clearUrl(key.ToString());

            try
            {
                // Clear data that is already saved by VisiBoard
                if (key != 0)
                {
                    request = (HttpWebRequest)WebRequest.Create(clear_url);
                    request.Timeout = _hardware_poll_timeout;
                    request.KeepAlive = false;
                    response = (HttpWebResponse)request.GetResponse();

                    // Clean up or else
                    response.Close();  // This is very important or you will run out of connections.
                    request = null;
                    response = null;
                }
            }
            catch (Exception ex)
            {
                FileLog.Error("URL: " + clear_url);
                FileLog.Error("Exception clearing data from VisiBox: ", ex);
            }

        }
#endif

        public  void clearEvents(int key, DateTime date)
        {
            System.Net.HttpWebRequest request;
            System.Net.HttpWebResponse response;

            string clear_url = clearUrl(key, string.Format("{0:O}", date));

            try
            {
                // Clear data that is already saved by VisiBoard
                    request = (HttpWebRequest)WebRequest.Create(clear_url);
                    request.Timeout = _hardware_poll_timeout;
                    request.KeepAlive = false;
                    response = (HttpWebResponse)request.GetResponse();

                    // Clean up or else
                    response.Close();  // This is very important or you will run out of connections.
                    request = null;
                    response = null;

            }
            catch (System.Exception ex)
            {
                FileLog.Error("URL: " + clear_url);
                FileLog.Error("Exception clearing data from VisiBox: ", ex);
            }
        }

        // Get the event at the top of the queue.  Return false if there is no data.
        public bool dequeueEvent(out VisiBoxEvent result)
        {
            // THREAD SAFE
            bool success = _events.TryDequeue(out result);

            return success;
        }

        // Callbacks for BackgroundWorker class
        private void workComplete(object sender, RunWorkerCompletedEventArgs e)
        {
            // Log any errors
            if (e.Error != null)
            {
                // TODO log e.Error.Message;
            }

            // Did this end prematurely??
            if (!_stopped)
            {
                Thread.Sleep(5000);
                if (!_stopped)
                    _worker.RunWorkerAsync();
            }
        }

        private void reportProgress(object sender, ProgressChangedEventArgs e)
        {
            if (_todo_when_data_available != null)
                _todo_when_data_available();
        }

        private bool queryAndProcessXML()
        {

            // REMEMBER THAT THIS HAPPENS IN A SEPARATE THREAD SO WORRY ABOUT THREAD SAFETY

            HttpWebRequest request;
            HttpWebResponse response;
            bool is_running = false;
            int key;

            int val;
            string reason;
            string negate;
            string when;
            DateTime time_stamp;
            VisiBoxEvent evt;
            VisiBoxError err = VisiBoxError.None;

            string mt;
            string get_url = getUrl();
            bool offline = (error() == VisiBoxError.Offline);

            try
            {
                request = (HttpWebRequest)WebRequest.Create(get_url);
                request.Timeout = _hardware_poll_timeout;
                request.KeepAlive = false;

                response = (HttpWebResponse)request.GetResponse();

                Stream st = response.GetResponseStream();
                StreamReader sr = new StreamReader(st);
                mt = sr.ReadToEnd();

                // Clean up or else.
                st.Close();
                sr.Close();
                response.Close();  // This is very important or you will run out of connections.
                request = null;
                response = null;

                // Only log XML with data to minimize the number of files.
                if (mt.IndexOf("no data", StringComparison.OrdinalIgnoreCase) < 0 && mt.Length > 2)
                    logXML(mt, get_url, "");

                if (mt.StartsWith("["))
                {
                    // JSON Data from new VisiBox
                    Newtonsoft.Json.JsonReader reader = new Newtonsoft.Json.JsonTextReader(new StringReader(mt));
                    reader.DateParseHandling = Newtonsoft.Json.DateParseHandling.None;
                    dynamic data = Newtonsoft.Json.Linq.JArray.Load(reader);

                    long status;
                    // System.Web.Helpers.Json.Decode(mt);
                    foreach (var item in data)
                    {

                        val = Convert.ToInt32(item.Value);
                        status = 0;

                        // Hack
                        if ((val & 1) > 0)
                            status += VisiBoxEvent.RUSCO_CYCLE_END;
                        if ((val & 2) > 0)
                            status += VisiBoxEvent.RUSCO_CYCLE_AUTO;
                        if ((val & 4) > 0)
                            status += VisiBoxEvent.RUSCO_ALARM;
                        if ((val & 8) > 0)
                            status += VisiBoxEvent.RUSCO_COOLANT;
                        if ((val & 16) > 0)
                            status += VisiBoxEvent.RUSCO_PART_CATCHER;

                        // 2015-06-26T23:56:45.0000000
                        var ds = Convert.ToString(item.Timestamp);

                        DateTime dt = DateTime.MinValue;
                        if (!DateTime.TryParse(ds, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.RoundtripKind, out dt))
                        {
                            dt = DateTime.ParseExact(ds, "O", System.Globalization.CultureInfo.InvariantCulture);
                        }
                        evt = new VisiBoxEvent(Convert.ToInt32(item.Id), dt, false, status);

                        if ((val & 1) > 0)
                            evt.appendReason("Cycle Complete");
                        if ((val & 2) > 0)
                            evt.appendReason("Auto Cycle");
                        if ((val & 4) > 0)
                            evt.appendReason("Alarm");
                        if ((val & 8) > 0)
                            evt.appendReason("Coolant");
                        if ((val & 16) > 0)
                            evt.appendReason("Part Catcher");

                        _events.Enqueue(evt);

                    }
                }
                else
                {
                    // XML from original boxes
                    XmlDocument doc = new XmlDocument();
                    doc.LoadXml(mt);

                    string xml_braider = doc.DocumentElement.Attributes["braider"] != null ? doc.DocumentElement.Attributes["braider"].Value : "";
                    string expected_braider = ((_braider_type == "RUSCO") ? "VBOX" : "IOBRD") + _cell_name;

#if DEBUG
                    if (get_url.Contains("visisuite.vnetsoftware.com"))
                        expected_braider = "IOBRD10"; // +_cell_name;
#endif

                    if (xml_braider.Length > 0 && xml_braider != expected_braider)
                    {
                        err = VisiBoxError.MismatchedBraider;
                    }
                    else
                    {

                        foreach (XmlElement parent in doc.DocumentElement)
                        {
                            if (parent.HasAttributes && (parent.Name.Equals("Event") || parent.Name.Equals("TimeStamp")))
                            {
                                key = Convert.ToInt32(parent.Attributes[0].Value);
                                when = (string)parent.Attributes[1].Value;

                                if (when.StartsWith("00-"))
                                {
                                    when = when.Replace("00-", "12-");
                                    when = when.Replace("-2014", "-2013");
                                    when = when.Replace("-2015", "-2014");
                                    when = when.Replace("-2016", "-2015");
                                    when = when.Replace("-2017", "-2016");
                                }

                                time_stamp = Convert.ToDateTime(when);

                                Console.WriteLine("key: " + key.ToString());

                                is_running = true;

                                evt = new VisiBoxEvent(key, time_stamp, offline);

                                foreach (XmlElement child in parent.ChildNodes)
                                {
                                    if (child.ParentNode.Name.Equals("Event") && child.Name.Equals("sensor"))
                                    {
                                        reason = (string)child.Attributes[0].Value;
                                        evt.appendReason(reason);
                                        Console.WriteLine("Reason: " + reason);
                                    }
                                    else if (child.ParentNode.Name.Equals("TimeStamp") && child.Name.Equals("event")) // OLD FIRMWARE > 1.0.1.10 AND < 1.0.1.22
                                    {
                                        val = Convert.ToInt32(child.Attributes[2].Value);
                                        // We only store reasons where value is set
                                        if (val == 1)
                                        {
                                            reason = (string)child.Attributes[1].Value;
                                            evt.appendReason(reason);
                                            is_running = false;
                                            Console.WriteLine("Reason: " + reason);
                                        }
                                    }
                                    else if (child.ParentNode.Name.Equals("TimeStamp") && child.Name.Equals("add"))  // OLD FIRMWARE < 1.0.1.10
                                    {

                                        val = Convert.ToInt32(child.Attributes[2].Value);
                                        negate = (string)child.Attributes[3].Value;
                                        if (negate == "true")
                                        {
                                            if (val == 0) val = 1;
                                            else val = 0;
                                        }

                                        // We only store reasons where value is set
                                        if (val == 1)
                                        {
                                            reason = (string)child.Attributes[1].Value;
                                            evt.appendReason(reason);
                                            is_running = false;
                                            Console.WriteLine("Reason: " + reason);
                                        }
                                    }
                                }

                                is_running = evt.isGoodEvent();
                                _events.Enqueue(evt);

                                machineRunning(is_running, DateTime.Now);

                            }
                        }
                    }

                    doc = null;
                    // GC.Collect();

                }

                Console.WriteLine("Processed XML from VisiBox");

            }
            catch (Exception ex)
            {
                FileLog.Error("Exception processing XML from VisiBox: ", ex);
                err = VisiBoxError.Offline;
            }

            if (err != error())
            {
                error(err);
            }

            return !_events.IsEmpty;

        }

        private bool verifyLocalIPAddress(string local_ip)
        {
            bool success = false;
            NetworkInterface[] nics = NetworkInterface.GetAllNetworkInterfaces();

            foreach (var adapter in nics)
            {
                IPInterfaceProperties props = adapter.GetIPProperties();

                foreach (var x in props.UnicastAddresses)
                {
                    if (x.Address.AddressFamily == AddressFamily.InterNetwork
                        && x.Address.ToString() == local_ip)
                    {
                        success = true;
                        break;
                    }
                }
            }

            return success;
        }

        private bool configureBraider(string local_ip)
        {

            // REMEMBER THAT THIS HAPPENS IN A SEPARATE THREAD SO WORRY ABOUT THREAD SAFETY

            HttpWebRequest request;
            HttpWebResponse response;
            bool success = false;

            if (verifyLocalIPAddress(local_ip))
            {

                try
                {
                    // Configure the braider VisiBox
                    // Hardcode 74 to be OMA
                    string braider = (_braider_type == "RUSCO") ? "4"  : ((_braider_type == "OMA") ? "2" : (_braider_type == "RB2" ? "1" : "0"));
                    string url = "http://" + _hardware_ip_address + "/cfg.htm?server=" + local_ip + "&heartbeat=60&braider=" + braider;

                    request = (HttpWebRequest)WebRequest.Create(url);
                    request.Timeout = _hardware_poll_timeout;
                    request.KeepAlive = false;
                    response = (HttpWebResponse)request.GetResponse();

                    // Clean up or else
                    response.Close();  // This is very important or you will run out of connections.
                    request = null;
                    response = null;
                    success = true;

                }
                catch (Exception ex)
                {
                    FileLog.Error("Exception configuring VisiBox: ", ex);
                    error(VisiBoxError.Offline);
                    success = false;
                }

            }

            return success;

        }

        public void enqueueMessageFromVisiBox(string msg)
        {
            if (!string.IsNullOrEmpty(msg))
            {
                _msg_queue.Enqueue(msg);
                error(VisiBoxError.None);
            }
            _msg_timeout_event.Set();
        }

        public bool dequeueMessageFromVisiBox(out string msg)
        {
            // TryDequeue() is THREAD SAFE by definition
            bool success = false;
            msg = null;

            if (_msg_queue != null)
                success = _msg_queue.TryDequeue(out msg);

            return success;
        }

        private void doWork(object sender, DoWorkEventArgs e)
        {

            // REMEMBER THAT THIS HAPPENS IN A SEPARATE THREAD SO WORRY ABOUT THREAD SAFETY

            BackgroundWorker worker = sender as BackgroundWorker;

            string expected_braider = ((_braider_type == "RUSCO") ? "VBOX" : "IOBRD" ) + _cell_name;
            bool query = false;
            string msg;
            DateTime now = DateTime.Now;
            DateTime last_heartbeat = now;

            bool polling = !string.IsNullOrEmpty(_hardware_url);

            enqueueMessageFromVisiBox(string.Format("heartbeat|{0}|1", _cell_name));

            Thread.Sleep(6000);  // let the system start up

            while (true)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }

                if (polling)
                {
                    // Using polling, wait for poll interval
                    query = true;
                    Thread.Sleep(_hardware_poll_interval);
                }
                else
                {

                    now = DateTime.Now;
                    TimeSpan diff = now.Subtract(last_heartbeat);
                    if (diff.TotalSeconds > 180.0)
                    {
                        // We have not heard from the box in 3 minutes, assume OFFLINE
                        _hardware_ip_address = "";
                        error(VisiBoxError.Offline);
                    }

                    // Wait for an event from UDP
                    _msg_timeout_event.WaitOne(_msg_timeout);

                    if (transitionedToOnline())
                    {
                        /***
                        udp.queueMessage("settime|" + now.ToString("yyyy-MM-dd HH:mm:ss"));
                        udp.queueMessage("queuemessage");
                        last_settime = now;
                         ***/
                        transitionedToOnline(false);
                    }

                    // Respond to messages
                    try
                    {
                        while (dequeueMessageFromVisiBox(out msg) == true)
                        {
                            string[] data = msg.Split('|');
                            if (data[1] == _cell_name)  // ignore data if not for this braider
                            {
                               
                                if (data[0] == "heartbeat")
                                {

                                    last_heartbeat = DateTime.Now;

                                    if (data[2] == "1")
                                        query = true;  // get data from VisiBox
                                }
                            }  
                        }

                    }
                    catch (Exception ex)
                    {
                        FileLog.Error("Error during UDP dequeue.", ex);
                    }

                }

                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }

                if (query == true)
                    queryAndProcessXML();

                if (!_events.IsEmpty)
                    worker.ReportProgress(1);

                query = false;

            }

            e.Result = true;
        }

        // Log the XMl to a file.
        private void logXML(string xml, string get_url, string clear_url)
        {

            var reg = RegistryHelper.OpenRegistryVisi(CommonConstants.RegistryVisiSuite, false);
            string log_dir = (string)reg.GetValue("LogDir");

            if (!String.IsNullOrEmpty(log_dir))
            {
                try
                {
                    TextWriter tw = File.CreateText(string.Format(@"{0}{1}.log", log_dir, DateTime.Now.ToString("yyyyMMddHHmmss.ffff")));
                    tw.WriteLine(get_url);
                    tw.WriteLine("");

                    tw.WriteLine(xml);

                    tw.WriteLine("");
                    tw.WriteLine(clear_url);
                    tw.Close();
                }
                catch (Exception ex)
                {
                    FileLog.Error("logXML()", ex);
                }
            }

        }

  
        #region UDP Message
#if FOO
        private void ListenUDPFromVisiBox()
        {
            var t = new Thread(new ThreadStart(() =>
            {
                bool done = false;
                Microsoft.Win32.RegistryKey reg;
                reg = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("SOFTWARE\\leanlogic\\VisiSuite");
                string _logDir = (string)reg.GetValue("LogDir");

                VisiBoardUtil.VisiBox.UDPService udpObj = new VisiBoardUtil.VisiBox.UDPService(54124);
                udpObj.LogDir = _logDir;
                try
                {
                    while (!done)
                    {
                        udpObj.ReceiveMessage();
                        if (udpObj.ErrorMessage == String.Empty)
                        {
                            string mes = String.Format("Received UDP message from {0} :\n {1}\n", udpObj.UdpFrom, udpObj.UDPReceiveMessage);
                            //Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => MessageBox.Show(mes)));
                            udpObj.LogUDPMessage();
                        }

                    }

                }
                catch (Exception e)
                {
                    //Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => MessageBox.Show(e.Message)));
                }

            }));
            t.Start();
        }
#endif
        #endregion
    }
}
